@file:Suppress("NOTHING_TO_INLINE")
package com.hzw.core.lazy

import com.hzw.core.thread.checkMainThread

internal val uninitializedValue = Any()
internal const val NOT_INITIALIZED = "懒加载的值还未被初始化"

fun <T> mainThreadLazy(initializer: () -> T): Lazy<T> = CheckedAccessLazyImpl(initializer, mainThreadChecker)

fun <T> checkedLazy(readChecker: () -> Unit, initializer: () -> T): Lazy<T> = CheckedAccessLazyImpl(initializer, readChecker)

internal class CheckedAccessLazyImpl<out T>(
    initializer: () -> T,
    private val readCheck: (() -> Unit)? = null,
    private var firstAccessCheck: (() -> Unit)? = null
) : Lazy<T> {

    private var initializer: (() -> T)? = initializer
    private var _value: Any? = uninitializedValue

    override val value: T
        get() {
            if (_value === uninitializedValue) {
                firstAccessCheck?.invoke() ?: readCheck?.invoke()
                _value = initializer!!()
                firstAccessCheck = null
                initializer = null
            } else readCheck?.invoke()
            @Suppress("UNCHECKED_CAST")
            return _value as T
        }

    override fun isInitialized(): Boolean = _value !== uninitializedValue
    override fun toString(): String = if (isInitialized()) value.toString() else NOT_INITIALIZED
}


@JvmField
internal val mainThreadChecker = { checkMainThread() }

fun accessOn(thread: Thread): () -> Unit = {
    Thread.currentThread().let {
        if (thread !== it) error("Access expected on thread: $thread. Current: $it")
    }
}

fun noAccessOn(thread: Thread): () -> Unit = {
    Thread.currentThread().let {
        if (thread === it) error("No access allowed on thread: $thread!")
    }
}
